package imdbfolder.data;

import imdbfolder.gui.ImdbFolderController;

import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.*;
import java.net.URL;
import java.util.HashMap;

public class MovieSelectionMap extends HashMap<String, Movie> {

    private static final long serialVersionUID = 1L;

    private static HashMap<File, MovieSelectionMap> instances = new HashMap<File, MovieSelectionMap>();

    private final File moviesFolder;

    private MovieSelectionMap(File moviesFolder) {
        if(!moviesFolder.exists()) {
            throw new IllegalArgumentException(moviesFolder.getAbsolutePath() + " does not exist");
        }

        this.moviesFolder = moviesFolder;
    }

    public synchronized static MovieSelectionMap getInstance() {
        return getInstance(ImdbFolderController.getInstance().getSelectedFolder());
    }

    public synchronized static MovieSelectionMap getInstance(File moviesFolder) {
        if (!instances.containsKey(moviesFolder)) {
            MovieSelectionMap selectionMap = new MovieSelectionMap(moviesFolder);
            selectionMap = selectionMap.loadFromCacheFile();

            instances.put(moviesFolder, selectionMap);
        }

        return instances.get(moviesFolder);
    }

    private MovieSelectionMap loadFromCacheFile() {
        File cacheFile = getCacheFile();

        MovieSelectionMap movieSelectionMap = null;

        if (cacheFile.exists()) {
            try {
                ObjectInputStream stream = new ObjectInputStream(new FileInputStream(cacheFile));
                movieSelectionMap = (MovieSelectionMap) stream.readObject();
                stream.close();
            }
            catch (FileNotFoundException e) {
                e.printStackTrace();
            }
            catch (IOException e) {
                e.printStackTrace();
            }
            catch (ClassNotFoundException e) {
                e.printStackTrace();
            }
        }

        // if the .imdbfolder folder is moved, we're looking at screwed up results, so discard the cached data if that's the case.
        if (movieSelectionMap == null || !movieSelectionMap.getMoviesFolder().equals(moviesFolder)) {
            return this;
        }
        else {
            return movieSelectionMap;
        }
    }

    public void saveToCacheFile() {
        File cacheFile = getCacheFile();

        try {
            ObjectOutputStream stream = new ObjectOutputStream(new FileOutputStream(cacheFile));
            stream.writeObject(this);
            stream.close();
        }
        catch (FileNotFoundException e) {
            e.printStackTrace();
        }
        catch (IOException e) {
            e.printStackTrace();
        }
    }

    public void putMovie(Movie movie) {
        put(movie.getFileName(), movie);

        saveToCacheFile();
    }

    public Movie getMovie(File file) {
        if (containsKey(file.getAbsolutePath())) {
            return get(file.getAbsolutePath());
        }
        else {
            return null;
        }
    }

    public void clearMovie(Movie movie) {
        remove(movie.getFileName());

        saveToCacheFile();
    }

    public File getCacheFile() {
        return new File(getDataFolder(), "movies.cache");
    }

    public void storeImage(String imageUrl, Movie movie) {
        try {
            BufferedImage bufferedImage = ImageIO.read(new URL(imageUrl));
            JPEGWriter.write(bufferedImage, 0.9f, new File(getDataFolder(), movie.getImdbId() + ".jpg"));
        }
        catch (IOException e) {
            e.printStackTrace();
        }
    }

    public Image getImage(Movie movie) {
        try {
            return ImageIO.read(new File(getDataFolder(), movie.getImdbId() + ".jpg"));
        }
        catch (IOException e) {
            e.printStackTrace();
        }

        return null;
    }

    public String getImagePath(Movie movie) {
        return new File(getDataFolder(), movie.getImdbId() + ".jpg").getAbsolutePath();
    }

    private File getDataFolder() {
        if(!moviesFolder.exists()) {
            throw new IllegalStateException(moviesFolder.getAbsolutePath() + " does not exist");
        }

        File directory = new File(moviesFolder, ".imdbfolder");

        if (!directory.exists()) {
            directory.mkdir();

            if (new File("C:\\WINDOWS\\System32\\ATTRIB.EXE").exists()) {
                try {
                    String command = "C:\\WINDOWS\\System32\\ATTRIB.EXE +H \"" + directory.getAbsolutePath() + "\"";
                    Runtime.getRuntime().exec(command);
                }
                catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }

        return directory;
    }

    public File getMoviesFolder() {
        return moviesFolder;
    }
}
